#ifndef __TOYM__NET__SOCK_OPT_H__
#define __TOYM__NET__SOCK_OPT_H__

struct sockaddr_in;

namespace toym
{
namespace net
{

struct SockOpt {

    /// @brief 创建一个不阻塞的，IPv4的TCP套接字描述符，只有成功时才返回
    /// @return 基于IPv4的TCO协议的套接字描述符
    static
    int createSocketUnblocked4();

    /// @brief 将套接字绑定到指定地址，相当于::bind的封装
    /// @param sockfd 套接字描述符
    /// @param paddr 要保定到的地址
    /// @return 成功返回0，不成功返回负值
    static
    int bind(int sockfd, const struct sockaddr_in* paddr);

    /// @brief 设置套接字为监听模式
    /// @param sockfd 套接字描述符
    /// @param nlisten 监听队列长度
    /// @return 成功返回0，不成功返回负值
    static
    int listen(int sockfd, int nlisten);

    /// @brief 从监听套接字中获取一个Tcp连接
    /// @param sockfd 监听套接字描述符
    /// @param paddr Tcp连接对方的地址
    /// @return 成功返回套接字描述符（>=0），失败返回负值
    static
    int accept(int sockfd, struct sockaddr_in* paddr);

    /// @brief 从监听套接字中获取一个Tcp连接，并设置为NONBLOCK和CLOEXEC
    /// @param sockfd 监听套接字描述符
    /// @param paddr Tcp连接对方的地址
    /// @return 成功返回套接字描述符（>=0），失败返回负值
    static
    int accept4(int sockfd, struct sockaddr_in* paddr);

    /// @brief 使用套接字连接到远程的地址
    /// @param sockfd 套接字描述符
    /// @param paddr 远程地址
    /// @return 成功返回0，失败返回负值
    static
    int connect(int sockfd, const struct sockaddr_in* paddr);

    /// @brief 关闭描述符的写端
    /// @param sockfd 套接字描述符
    /// @return 成功返回0，失败返回负值
    static
    int shutdownWrite(int sockfd);

    /// @brief 将套接字设置为非阻塞
    /// @param sockfd 套接字描述符
    /// @return 成功返回0，失败返回负值
    static
    int setUnblocked(int sockfd);

    /// @brief 获取套接字描述符绑定的对方的地址
    /// @param sockfd 套接字描述符
    /// @param paddr 输出的对方地址
    /// @return 成功返回0，失败返回负值
    static
    int getPeerAddr(int sockfd, struct sockaddr_in* paddr);

    /// @brief 获取套接字描述符绑定的己方的地址
    /// @param sockfd 套接字描述符
    /// @param paddr 输出己方地址
    /// @return 成功返回0，失败返回负值。
    static
    int getLocalAddr(int sockfd, struct sockaddr_in* paddr);

    /// @brief 设置套接字为可重用地址
    /// @param sockfd 套接字描述符
    /// @param reuse 是否重用
    /// @return 成功返回0，失败返回负值
    static
    int setSocketReuse(int sockfd, bool reuse);

    /// @brief 设置Tcp的Nagle算法（Nagle算法会延迟到一定数据量才会发包，导致延迟提高）
    /// @param sockfd Tcp套接字描述符
    /// @param on true关闭Nagle算法，false开启Nagle算法
    /// @return 成功返回0，失败返回负值
    static
    int setTcpNoDelay(int sockfd, bool on);

    /// @brief 设置发送心跳包确保对方一直在线
    /// @param sockfd Tcp套接字描述符
    /// @param on true设置发送，false设置不发送
    /// @return 成功返回0，失败返回负值
    static
    int setKeepAlive(int sockfd, bool on);

    /// @brief 使用getsockopt获取socket的出错情况(SO_ERROR)
    /// @param sockfd socket
    /// @return 出错情况
    static
    int getSocketError(int sockfd);

    /// @brief 检查sockfd是不是自连接
    /// @param sockfd 套接字描述符
    /// @return 自连接返回true，不是自连接返回false
    static
    bool isSelfConnect(int sockfd);
};

} // namespace net

} // namespace toym


#endif // __TOYM__NET__SOCK_OPT_H__